package com.dxy.dataManage.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dxy.dataManage.bean.File;
import com.dxy.dataManage.bean.Msg;
import com.dxy.dataManage.mapper.FileMapper;
import com.dxy.dataManage.service.FileService;
import com.dxy.dataManage.urils.FileUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author dxy
 * @version 1.0
 */
@Slf4j
@Controller
public class FileController {
    @Resource
    private FileService fileService;

    @Resource
    private FileMapper fileMapper;

    //用于登录后刷新页面的方法，返回自己公司的文件列表
    @GetMapping("/listFile")
    @ResponseBody
    public Msg listFileByComName(@RequestParam(defaultValue = "1") Integer pageNum,
                        @RequestParam(defaultValue = "5") Integer pageSize,
                        @RequestParam("componyName") String componyName) {
        PageHelper.startPage(pageNum, pageSize);//这行是重点（放在方法第一行）表示从pageNum页开始，每页pageSize条数据
        List<File> fileList = fileMapper.listFileByComName(componyName);//返回集合和分页之前不要有其它代码，这两行上下要紧靠近
        PageInfo<File> pageInfo = new PageInfo<>(fileList);
        log.info("pageNum=> " + pageNum + "pageSize=> " + pageSize + "componyName=> " + componyName);
        return Msg.success().add("pageInfo", pageInfo);
    }
    //用于查询文件名的方法，返回对应文件列表，（仅自己公司）
    @GetMapping("/listFileBySearch")
    @ResponseBody
    public Msg listFileBySearch(@RequestParam(defaultValue = "1") Integer pageNum,
                                 @RequestParam(defaultValue = "5") Integer pageSize,
                                 @RequestParam("componyName") String componyName,
                              @RequestParam("search") String search) {
        PageHelper.startPage(pageNum, pageSize);//这行是重点（放在方法第一行）表示从pageNum页开始，每页pageSize条数据
        List<File> fileList = fileMapper.listFileBySearch(componyName, search);//返回集合和分页之前不要有其它代码，这两行上下要紧靠近
        PageInfo<File> pageInfo = new PageInfo<>(fileList);
        log.info("pageNum=> " + pageNum + "pageSize=> " + pageSize + "componyName=> " + componyName);
        return Msg.success().add("pageInfo", pageInfo);
    }
//    @RequestMapping("/listFileBySearchOrType")
//    @ResponseBody
//    public Msg listFileByName(@RequestParam("search") String name,
//                              @RequestParam("type") String type,
//                              @RequestParam("componyName") String componyName,
//                              @RequestParam(defaultValue = "1") Integer pageNum,
//                              @RequestParam(defaultValue = "5") Integer pageSize,
//                              HttpServletRequest request) {
//        System.out.println("name => " + name);
//        System.out.println("type => " + type);
//        System.out.println("pageNum => " + pageNum);
//        System.out.println("pageSize => " + pageSize);
//
//
//        List<File> fileList = fileService.listFileByNameOrType(name, type, componyName);  //因而获得的是分好页的结果集
////        列表为空就不进行分页，防止空指针
//        if (null != fileList) {
//return null;
//        }
//        return Msg.success();
//    }


//    用于修改文件时，通过文件id来修改文件信息
    @GetMapping("/find")
    @ResponseBody
    public Msg find(@RequestParam("id") Long id) {
        File file = fileService.getById(id);
        return Msg.success().add("file", file);
    }

    //@RequestMapping("/findByType")
    //@ResponseBody
    //public Msg findByType(@RequestParam("type") String type,
    //                      @RequestParam("componyName") String componyName) {
    //    System.out.println("type = " + type);
    //    List<File> files = fileService.findByType(type, componyName);
    //    return Msg.success().add("files", files);
    //}




    //用于删除文件
    @DeleteMapping(value = "/del/{id}")
    @ResponseBody
    public Msg del(@PathVariable Long id) {
        fileService.removeById(id);
        Msg msg = Msg.success();
        return msg;
    }

    //用于修改文件
    @RequestMapping("/update")
    @ResponseBody
    public Msg updateFile(@RequestBody File file) {
        if (fileService.saveOrUpdate(file)) {
            return Msg.success();
        }
        return Msg.fail();
    }



//    @GetMapping("/list")
//    @ResponseBody
//    public Msg list(
//            @RequestParam("componyName") String componyName,
//            @RequestParam(defaultValue = "1") Integer pageNum,
//            @RequestParam(defaultValue = "5") Integer pageSize) {
//
//        PageHelper.startPage(pageNum, pageSize);
//        List<File> fileList = fileService.listFileByNameOrType("", "", componyName);
////        列表为空就不进行分页，防止空指针
//        if (null != fileList) {
//            PageInfo pageInfo = new PageInfo(fileList, pageSize);
//            return Msg.success().add("pageInfo", pageInfo);
//        }
//        return Msg.fail().add("message", "查询失败");
//    }

    //用于上传文件时保存文件的相关信息到数据库
    @PostMapping("/saveFileInfo")
    @ResponseBody
    public Msg saveFileInfo(@RequestBody File file) {
        System.out.println(file);

        if (fileService.save(file)) {
            return Msg.success().add("message", "文件保存成功");
//            return "forward:/listFileBySearchOrType";
        } else {
            return Msg.fail().add("message", "文件保存失败");
        }
    }


    //用于保存上传的文件到指定目录
    @PostMapping("/fileUpload")
    @ResponseBody
    public Msg fileUpload(@RequestPart("file") MultipartFile[] files) throws IOException {
        String urlList = fileService.fileUpload(files);
        if (StringUtils.hasText(urlList)) {
            return Msg.success().add("urlList", urlList);
        }
        System.out.println("fileUpload 被访问");
        return Msg.fail().add("message", "无文件上传完成");
    }

    //用于返回需用户自己处理的文件
    @GetMapping("/myProcess/{id}")
    @ResponseBody
    public Msg getProcessFile(@PathVariable("id") Long id) {
        return Msg.success().add("files", fileService.getProcessFile(id));
    }

    //下载文件
    //通过id获取file对象的url，进而通过io流返回 ResponseEntity<byte[]> 对象
    //测试返回图片列表
    @GetMapping("/fileDown/{id}")
    public void downFile(@PathVariable("id") Long id,
                         HttpSession session,
                         HttpServletResponse response) throws Exception {
        //通过id获取文件info对象
        System.out.println("id=> " + id);
        File file = fileService.getById(id);
        //排除不存在
        try {
            if (null == file || "null".equals(file.getUrl()) || !StringUtils.hasText(file.getUrl())) {
                response.getWriter().write("无图片");
            }
        } catch (Exception e) {
        }
        String urlStr = file.getUrl();
        //多个url通过 ; 分开，判断是否为多个并调用 getFilesByUrl 方法
        //最终返回 ResponseEntity<byte[]> 对象
        byte[] filesByUrl;
        List<String[]> list = FileUtils.getNamesAndPathsList(urlStr);
        String[] names = list.get(0);
        String[] paths = list.get(1);
        getFilesByUrl(names, paths, file.getName(), session, response);
    }

    //已经可以正确返回png图片的方法
    //@GetMapping("/fileDown/{id}")
    //public void downFile1(@PathVariable("id") Long id,
    //                      HttpSession session,
    //                      HttpServletResponse response) throws Exception {
    //    //通过id获取文件info对象
    //    System.out.println("id=> " + id);
    //    File file = fileService.getById(id);
    //    //排除不存在
    //    try {
    //        if (null == file || "null".equals(file.getUrl()) || !StringUtils.hasText(file.getUrl())) {
    //            response.getWriter().write("无图片");
    //        }
    //    } catch (Exception e) {
    //    }
    //    String urlStr = file.getUrl();
    //    //多个url通过 ; 分开，判断是否为多个并调用 getFilesByUrl 方法
    //    //最终返回 ResponseEntity<byte[]> 对象
    //    byte[] filesByUrl;
    //    if (urlStr.contains(";")) {
    //        String[] split = urlStr.split(";");
    //        filesByUrl = getFilesByUrl(split[0], session, response);
    //        response.getOutputStream().write(filesByUrl);
    //    } else {
    //        filesByUrl = getFilesByUrl(urlStr, session, response);
    //        System.out.println(filesByUrl.length);
    //        response.getOutputStream().write(filesByUrl);
    //    }
    //}

    //多文件下载，用于获取文件输入流，并压缩输出至指定目录
    public void getFilesByUrl(String[] names, String[] paths, String fileName, HttpSession session, HttpServletResponse response) throws IOException {
        //创建临时目录以存放生成的压缩包文件
        String directory = "D:\\文件压缩包临时目录";
        java.io.File directoryFile = new java.io.File(directory);

        //设置最终输出zip文件的目录+文件名
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
        String zipFileName = fileName + "---" + formatter.format(new Date()) + "下载.zip";
        String strZipPath = directory + "\\" + zipFileName;

        //创建流
        ZipOutputStream zipStream = null;
        FileInputStream zipSource = null;
        BufferedInputStream bufferStream = null;
        java.io.File zipFile = new java.io.File(strZipPath);
        try {
            //构造最终压缩包的输出流
            zipStream = new ZipOutputStream(new FileOutputStream(zipFile));
            for (int i = 0; i < paths.length; i++) {
                //解码获取真实路径与文件名
                String realFileName = java.net.URLDecoder.decode(names[i], "UTF-8");
                String realFilePath = java.net.URLDecoder.decode(paths[i], "UTF-8");
                java.io.File file = new java.io.File(realFilePath);
                if (file.exists()) {
                    zipSource = new FileInputStream(file);//将需要压缩的文件格式化为输入流
                    ZipEntry zipEntry = new ZipEntry(realFileName);//在压缩目录中文件的名字
                    zipStream.putNextEntry(zipEntry);//定位该压缩条目位置，开始写入文件到压缩包中
                    bufferStream = new BufferedInputStream(zipSource, 1024 * 10);
                    int read = 0;
                    byte[] buf = new byte[1024 * 10];
                    while ((read = bufferStream.read(buf, 0, 1024 * 10)) != -1) {
                        zipStream.write(buf, 0, read);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (null != bufferStream) bufferStream.close();
                if (null != zipStream) {
                    zipStream.flush();
                    zipStream.close();
                }
                if (null != zipSource) zipSource.close();
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }

        if (zipFile.exists()) {
            downImg(response, zipFileName, strZipPath);
            zipFile.delete();
        }
    }

    //多文件下载，用于从指定的压缩目录返回文件输出流给前端
    public void downImg(HttpServletResponse response, String filename, String path) {
        if (filename != null) {
            FileInputStream is = null;
            BufferedInputStream bs = null;
            OutputStream os = null;
            try {
                java.io.File file = new java.io.File(path);
                if (file.exists()) {
                    //设置Headers
                    response.setHeader("Content-Type", "application/zip");
                    //设置下载的文件的名称-该方式已解决中文乱码问题
                    response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
                    is = new FileInputStream(file);
                    bs = new BufferedInputStream(is);
                    os = response.getOutputStream();
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    while ((len = bs.read(buffer)) != -1) {
                        os.write(buffer, 0, len);
                    }
                } else {
                    String error = Base64Util.encode("下载的文件资源不存在");
                    response.sendRedirect("/imgUpload/imgList?error=" + error);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                    if (bs != null) {
                        bs.close();
                    }
                    if (os != null) {
                        os.flush();
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        ////已经可以正确返回png图片的方法
        //public byte[] getFilesByUrl (String url, HttpSession session, HttpServletResponse response) throws IOException
        //{
        //    //获取文件名
        //    java.io.File file = new java.io.File(url);
        //    String fileName = new String(file.getName().getBytes("UTF-8"), "iso-8859-1");
        //    //获取输入流、输出流
        //    FileInputStream fis = new FileInputStream(file);
        //    BufferedInputStream bis = new BufferedInputStream(fis);
        //    ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //    //开辟一个存放文件内容 byte 数组,因为 byte 是字节，因此可以返回二进制的文件【图片，视频。。】
        //    byte[] bytes;//用来保存文件
        //    byte[] b = new byte[1024];
        //    int len;
        //    while ((len = bis.read(b)) != -1) {
        //        bos.write(b, 0, len);
        //    }
        //    bytes = bos.toByteArray();//保存完成
        //    //构建返回的 ResponseEntity<byte[]>
        //    //HttpStatus statuts = HttpStatus.OK;//返回成功
        //    //HttpHeaders headers = new HttpHeaders();//根据 http 协议这个就是告诉浏览器，这是返回的一个文件, 浏览器就弹出小窗口
        //    response.setHeader("Content-Disposition", "inline;filename=" + fileName);
        //    //headers.setContentType(new MediaType("image", "png"));
        //    //return new ResponseEntity(bytes, headers, statuts);
        //    response.setContentType("image/png");
        //
        //    System.out.println(bytes.length);
        //    return bytes;
        //}
    }
